package com.onpositive.data.serializer.readers;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;

import com.onpositive.data.AbstractReader;
import com.onpositive.data.IPropertyConstants;
import com.onpositive.data.IPropertyMetadata;
import com.onpositive.data.diskstorage.IReaderFactory;

public class DefaultReaderFactory implements IReaderFactory {
	
	private static DefaultReaderFactory instance = null ;
	
	public static DefaultReaderFactory getInstance(){
		
		if( instance == null )
			instance = new DefaultReaderFactory() ;
		
		return instance ;
	}
	
	public static final int RW_ID_DOUBLE = 1 ;
	public static final int RW_ID_INTEGER = 2 ;
	public static final int RW_ID_DATE = 3 ;
	public static final int RW_ID_STRING = 4 ;
	public static final int RW_ID_STRING_ITERABLE = 5 ;
	public static final int RW_ID_BYTE_ARRAY = 6 ;
	public static final int RW_ID_NUMBER_QUANIFIER = 7 ;
	public static final int RW_ID_DATE_WITH_ACCURACY = 8 ;
	public static final int RW_ID_RANGE_QUANIFIER = 9 ;
	public static final int RW_ID_DATE_RANGE = 10;
	
	private HashMap< Integer, Constructor<?> > constructorMap ;
	
	private DefaultReaderFactory(){
		
		constructorMap = new HashMap< Integer, Constructor<?>>();
		try {
			constructorMap.put( RW_ID_DOUBLE  , DoubleReader.class.getConstructor() 	) ;
			constructorMap.put( RW_ID_INTEGER , IntReader.class.getConstructor()		) ;
			constructorMap.put( RW_ID_DATE	  , DateReader.class.getConstructor()		) ;
			constructorMap.put( RW_ID_STRING  , StringReader.class.getConstructor()		) ;
			constructorMap.put( RW_ID_STRING_ITERABLE , StringIterableReader.class.getConstructor() ) ;
			constructorMap.put( RW_ID_BYTE_ARRAY , ByteArrayReader.class.getConstructor() ) ;
			constructorMap.put( RW_ID_NUMBER_QUANIFIER , NumericValuesCollectionReader.class.getConstructor() ) ;
			constructorMap.put( RW_ID_DATE_WITH_ACCURACY , DateWithAccuracyReader.class.getConstructor() ) ;
			constructorMap.put( RW_ID_RANGE_QUANIFIER , RangeReader.class.getConstructor() ) ;
			constructorMap.put( RW_ID_DATE_RANGE , DateRangeReader.class.getConstructor() ) ;
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}		
	}
	
	@Override
	public AbstractReader<?> createReader( int id, IPropertyMetadata meta )
	{
		if (id==Integer.MIN_VALUE){
			Object value = meta.getValue(IPropertyConstants.CHAR_PARSER_ID_LABEL);
			if (value.equals(IPropertyConstants.PROP_KIND_DIMENSION)){
				return new RangeReader();
			}
			if (value.equals(IPropertyConstants.PROP_KIND_FILE_LIST)){
				return new StringIterableReader();
			}
			if (value.equals(IPropertyConstants.PROP_KIND_DATE)){
				return new DateRangeReader();
			}
			if (value.equals(IPropertyConstants.PROP_KIND_SCALAR)){
				return new RangeReader();
			}
			return new StringReader();
		}
		Constructor<?> constructor = constructorMap.get( id ) ;
		
		try {
			
			Object result = constructor.newInstance() ;
			return (AbstractReader<?>) result;
			
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
			return null;
		} catch (InstantiationException e) {
			e.printStackTrace();
			return null;
		} catch (IllegalAccessException e) {
			e.printStackTrace();
			return null;
		} catch (InvocationTargetException e) {
			e.printStackTrace();
			return null;
		}
	}


}
